package test;


import static org.junit.Assert.*;

import java.io.IOException; 
import java.net.SocketException; 
import java.util.ArrayList;

import org.junit.Assert;
import org.junit.Test;


import Phase1.*; 
import Phase2.Node;
/**
 * White Box Testing for Server / Client part.
 * 
 * @author djb0646
 *
 */
public class testWhiteCommunication 
{
	private Server server;
  
	
	/**
	 * control flow /Data flow testing of processRequest  
	 * 
	 * + together with muti-thread testing.(workers)
	 */ 
	@Test
	public void testControlAndDataflow() throws Exception
	{
		showThreads();
		server = new Server();
		showThreads();
		
		// is string?
		try 
		{
			String str = "yes";
			
			assertEquals(str, Client.sendData("127.0.0.1", 3000, str));
		} 
		catch (IOException e) 
		{  
			//catch might skiped in coverage test
			e.printStackTrace();
			
		} 
		catch (ClassNotFoundException e) 
		{ 
			e.printStackTrace();
			//catch might skiped in coverage test
		}
		//is port?
		try 
		{
			Port port = new Port(203);
			
			assertNull(Client.sendData("127.0.0.1", 3000, port));
		} 
		catch (IOException e) 
		{
			 
			e.printStackTrace();
			//catch might skiped in coverage test
		} 
		catch (ClassNotFoundException e) 
		{
			 
			e.printStackTrace();
			//catch might skiped in coverage test
		}
		// is other object?
		try 
		{
			double[] temp = {1, 2, 3, 4, 5};
			assertNull(Client.sendData("127.0.0.1", 3000, temp));
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
			//catch might skiped in coverage test
		} 
		catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
			//catch might skiped in coverage test
		}
		//is command?
		/*try 
		{ 
			 
			GlobalID fakeId = new GlobalID("localhost", 3000, new LocalID());
			Class<?>[] parameterTypes = new Class<?>[] {int.class};
			Object[] parameters = new Object[] {new Integer(0)};
			
			assertTrue(null == Client.sendData(fakeId, new Command(fakeId, "charAt", parameterTypes, parameters, true)));
			
		} 
		catch (AssertionError e)
		{
			Assert.assertTrue(true);
		}
		catch (IOException e) 
		{
			e.printStackTrace();
			//catch might skiped in coverage test
		} 
		catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
			//catch might skiped in coverage test
		}*/
		showThreads();
		
		server.done();
		showThreads();
		
	}
	 
	/**
	 * boundary testing
	 */
	@Test
	public void testDataFlow() throws IOException
	{ 
		//intended to go error catching part
		showThreads();
		Server s = null;
		showThreads();
		//server port limit >1024
		try 
		{ 
			 
			s = new Server(1023); 
			assertTrue(false);
			
		} 
		catch (IOException e)
		{
			//catch might skiped in coverage test
			assertTrue(true);
		}
		catch (AssertionError e)
		{ 
			//catch might skiped in coverage test
			
			Assert.assertTrue(true);
			
		}
		finally
		{
			if(s != null)
			{
				s.done();
				s = null;
			}
		}
		//server port limit >1024
		try 
		{ 
			 
			s = new Server(1024); 
			assertTrue(false);
			
		} 
		catch (AssertionError e)
		{
			//catch might skiped in coverage test
			Assert.assertTrue(true);
		}
		finally
		{
			if(s != null)
			{
				s.done();
				s = null;
			}
		}
		//server port limit >1024
		try 
		{ 
			 
			s = new Server(1025); 
			 
			
		} 
		catch (AssertionError e)
		{//catch might skiped in coverage test
			Assert.assertTrue(false);
		}
		finally
		{
			if(s != null)
			{
				s.done();
				s = null;
			}
		}
		//server port limit <65536
		try 
		{ 
			 
			s = new Server(65535);  
			
		} 
		catch (AssertionError e)
		{//catch might skiped in coverage test
			Assert.assertTrue(false);
		}
		finally
		{
			if(s != null)
			{
				s.done();
				s = null;
			}
		}
		//server port limit <65536
		try 
		{ 
			 
			s = new Server(65536); 
			assertTrue(false);
			
		} 
		catch (IOException e)
		{//catch might skiped in coverage test
			assertTrue(true);
		}
		catch (AssertionError e)
		{//catch might skiped in coverage test
			Assert.assertTrue(true);
		} 
		finally
		{
			if(s != null)
			{
				s.done();
				s = null;
			}
		}
		 
		showThreads();
	}
	/**
	 * testing for database.
	 */ 
	@Test
	public void testDB() throws InterruptedException
	{
		showThreads();
		ObjectDB database =  ObjectDB.getDatabase();
		print("|TEST| no of node in db: " + database.getAllKeys().size());
		server = new Server();
		Node root = new Node();
		database.put(root.getGlobalID(), root);
		//print("|RETURN| " + server.getFreeWorkSpace().processingRequest(new Node()));
		for(int i = 0; i < 5; i++)
		{ 
			Node temp = new Node();
			server.getFreeWorkSpace().processingRequest(temp);
			database.put(temp.getGlobalID(), temp); 
			print("|TEST| no of node in db: " + database.getAllKeys().size());
				 
		}
		print("|TEST| no of node in db: " + database.getAllKeys().size());
		
		server.done();
		try 
		{
			Thread.sleep(500);
		} catch (InterruptedException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		showThreads(); 
		Node root1 = new Node();
		for(int i = 0; i < 5; i++)
		{
			root1.insert(new Node());
		}
		assertEquals(root.printAllNode(), root1.printAllNode());
		print("|TEST| no of node in db: " + database.getAllKeys().size());
		
	}
	 
	 
		
	
	 
	/**
	 * Server should be halt by its listener if connection setup without message .
	 */
	@Test
	public void testClientHalt()  
	{
		System.out.println("testing for Halt");
		showThreads();
		
		server = new Server();
		showThreads();
		 
		try 
		{
			Client.setLinkToServer("127.0.0.1", 3000);
		}
		catch (SocketException e) 
		{
			assertTrue(true);
		}
		catch (ClassNotFoundException e) 
		{
			//catch might skiped in coverage test
			e.printStackTrace();
		}
		catch (IOException e)
		{
			//catch might skiped in coverage test
			e.printStackTrace();
		}
	 
		server.done(); 
		try 
		{
			Thread.sleep(5000);
		} catch (InterruptedException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		showThreads();
		
	}
	/**
	 * testing for catch error if client calls the wrong socket. 
	 */
	@Test
	public void testWrongSocket()  
	{
		//intended to go error catching part.
		System.out.println("testing for halt other socket");
		server = new Server();
		 
		try 
		{
			Client.setLinkToServer("127.0.0.1", 3001);
		}
		catch (SocketException e) 
		{
			//Intended to go here for error
			// TODO Auto-generated catch block
			assertTrue(true);
		}
		catch (ClassNotFoundException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e)
		{
			//catch might skiped in coverage test
			e.printStackTrace();
		}
	 
		server.done(); 
	}
	/**
	 * testing for customize server socket
	 */
	@Test
	public void testOtherSocket() throws IOException
	{
		System.out.println("testing for other socket");
		server = new Server(5555);
		 
		try 
		{
			assertEquals("hello", Client.sendData("127.0.0.1", 5555, "hello"));
		}
		catch (SocketException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			assertTrue(true);
		}
		catch (ClassNotFoundException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e)
		{
			//catch might skiped in coverage test
			e.printStackTrace();
		}
	 
		server.done();
		showThreads();
	}
	/**
	 * print parameter
	 * @param o
	 * object to be printed
	 */
	public static void print(Object o)
	{
		System.out.println(o);
	}
	 
	/**
	 * shows current thread number
	 * @return 
	 * current threads number
	 */
	public static int showThreads()
	{
	
		try 
		{
			Thread.sleep(500);
		} catch (InterruptedException e) 
		{
			//catch might skiped in coverage test
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("|TESTING| current Threads: " + Thread.getAllStackTraces().size());
		return Thread.getAllStackTraces().size();
	}
	 
}